home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src_ansi / ace / c / libfunc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-05  |  14.8 KB  |  652 lines

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: library and machine code function handling **
  6.    ** Copyright (C) 1998 David Benn
  7.    ** 
  8.    ** This program is free software; you can redistribute it and/or
  9.    ** modify it under the terms of the GNU General Public License
  10.    ** as published by the Free Software Foundation; either version 2
  11.    ** of the License, or (at your option) any later version.
  12.    **
  13.    ** This program is distributed in the hope that it will be useful,
  14.    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    ** GNU General Public License for more details.
  17.    **
  18.    ** You should have received a copy of the GNU General Public License
  19.    ** along with this program; if not, write to the Free Software
  20.    ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22.    Author: David J Benn
  23.    Date: 26th October-30th November, 1st-13th December 1991,
  24.    14th,20th-27th January 1992, 
  25.    2nd-17th, 21st-29th February 1992, 
  26.    1st,13th,14th,22nd,23rd March 1992,
  27.    21st,22nd April 1992,
  28.    2nd,3rd,11th,15th,16th May 1992,
  29.    7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
  30.    2nd-8th,14th-19th,26th-29th July 1992,
  31.    1st-3rd,7th,8th,9th August 1992,
  32.    6th,7th,22nd December 1992,
  33.    28th February 1993,
  34.    12th April 1993,
  35.    16th,17th December 1993,
  36.    2nd,3rd,13th January 1994,
  37.    12th June 1994,
  38.    5th,20th,28th August 1994,
  39.    1st,10th September 1994,
  40.    8th,9th March 1995
  41.  */
  42.  
  43. #include "acedef.h"
  44. #include <string.h>
  45. #include <clib/dos_protos.h>
  46.  
  47. /* locals */
  48. static char *reg[] =
  49. {"  ", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  50.  "a0", "a1", "a2", "a3", "a4", "a5"};
  51.  
  52. /* externals */
  53. extern int sym;
  54. extern int lastsym;
  55. extern int typ;
  56. extern int lev;
  57. extern char id[MAXIDSIZE];
  58. extern char ut_id[MAXIDSIZE];
  59. extern char tempshortname[80];
  60. extern char templongname[80];
  61. extern char stringval[MAXSTRLEN];
  62. extern SYM *curr_item;
  63. extern ACELIBS acelib[NUMACELIBS];
  64. extern ACELIBS otherlib[NUMLIBS];
  65. extern char librarybase[MAXIDSIZE + 6];
  66. extern char libraryname[MAXIDSIZE + 20];
  67. extern char bmapname[MAXIDSIZE + 20];
  68. extern BOOL restore_a4;
  69. extern BOOL restore_a5;
  70. extern BOOL early_exit;
  71.  
  72. /* ------------------------- */
  73. /* Library Function routines */
  74. /* ------------------------- */
  75.  
  76. BYTE check_for_ace_lib (char *libname)
  77. {
  78.   BYTE c = 0;
  79. /* 
  80.    ** If libname is a library used by ACE 
  81.    ** open & close it in the normal way.
  82.  */
  83.  
  84.   while (acelib[c].name[0] != '\0' &&     strcmp (acelib[c].name, "SENTINEL") != 0)
  85.     {
  86.       if (strcmp (acelib[c].name, libname) == 0)
  87.     {
  88.       enter_XREF (acelib[c].base);
  89.       return (c);
  90.     }
  91.       c++;
  92.     }
  93.   return (NEGATIVE);
  94. }
  95.  
  96. void enter_new_library (char *libname)
  97. {
  98.   int cc = 0;
  99. /*
  100.    ** Enter a library into the list 
  101.    ** for future reference by function
  102.    ** declarations which don't specify
  103.    ** the library to be used.
  104.  */
  105.  
  106.   /* 
  107.      ** Find libname, first free or maximum entry.
  108.      ** If it's already in the list, libname will
  109.      ** be ignored.  
  110.    */
  111.   while (otherlib[cc].name[0] != '\0' &&
  112.      strcmp (otherlib[cc].name, libname) != 0 &&
  113.      strcmp (otherlib[cc].name, "SENTINEL") != 0)
  114.     cc++;
  115.  
  116.   /* maximum? */
  117.   if (strcmp (otherlib[cc].name, "SENTINEL") == 0)
  118.     _error (76);        /* can't add another library */
  119.   else if (otherlib[cc].name[0] == '\0')
  120.     {
  121.       /* add a new entry */
  122.       strcpy (otherlib[cc].name, libname);
  123.       make_library_base (libname);
  124.       strcpy (otherlib[cc].base, librarybase);
  125.     }
  126. }
  127.  
  128. void make_library_base (char *libname)
  129. {
  130.   strcpy (librarybase, "_\0");
  131.   strcat (librarybase, libname);
  132.   strcat (librarybase, "Base");
  133.   enter_BSS (librarybase, "ds.l 1");
  134. }
  135.  
  136. void make_library_name (char *libname)
  137. {
  138.   strcpy (libraryname, libname);
  139.   strcat (libraryname, ".library");
  140. }
  141.  
  142. void make_bmap_name (char *libname)
  143. {
  144.   strcpy (bmapname, "ACEbmaps:");
  145.   strcat (bmapname, libname);
  146.   strcat (bmapname, ".bmap");
  147. }
  148.  
  149. void get_libname (char *libname, char *ut_libname)
  150. {
  151.   char *tmp, *ut_tmp;
  152.  
  153.   /* get raw library name (uppercase and untouched) */
  154.   if (sym == ident)
  155.     {
  156.       strcpy (ut_libname, ut_id);
  157.       strcpy (libname, id);
  158.     }
  159.   else
  160.     {
  161.       strcpy (ut_libname, stringval);
  162.       strcpy (libname, strupr (stringval));
  163.     }
  164.  
  165.   /* chop off extension if ".bmap" or ".library" */
  166.   tmp = libname;
  167.   ut_tmp = ut_libname;
  168.   while (*tmp && *tmp != '.')
  169.     {
  170.       tmp++;
  171.       ut_tmp++;
  172.     }
  173.   if (*tmp == '.' &&
  174.       (strcmp (tmp, ".BMAP") == 0 || strcmp (tmp, ".LIBRARY") == 0))
  175.     {
  176.       *tmp = '\0';
  177.       *ut_tmp = '\0';
  178.     }
  179. }
  180.  
  181. void library (void)
  182. {
  183.   char libname[MAXIDSIZE], ut_libname[MAXIDSIZE];
  184.   char lab[80], lablabel[80];
  185.  
  186.   /* open or close a shared library */
  187.  
  188.   insymbol ();
  189.   if (sym == closesym)
  190.     closelibrary ();
  191.   else
  192.     {
  193.       if (sym != ident && sym != stringconst)
  194.     _error (7);        /* identifier expected */
  195.       else
  196.     {
  197.       get_libname (libname, ut_libname);    /* without extension! */
  198.  
  199.       if (check_for_ace_lib (libname) == NEGATIVE)
  200.         {
  201.           make_library_name (ut_libname);    /* exec names are case sensitive */
  202.           make_string_const (libraryname);
  203.           gen ("move.l", "(sp)+", "a1");    /* address of library name in a1 */
  204.           gen ("jsr", "_open_library", "  ");
  205.           make_library_base (libname);
  206.           gen ("move.l", "d0", librarybase);
  207.           gen ("cmpi.l", "#0", "d0");
  208.           make_label (lab, lablabel);
  209.           gen ("bne.s", lab, "  ");
  210.           gen ("jmp", "_EXIT_PROG", "  ");    /* quit program if can't open library */
  211.           gen (lablabel, "  ", "  ");
  212.           enter_XREF ("_open_library");
  213.  
  214.           /* enter new library info' into "other libraries" list */
  215.           enter_new_library (libname);
  216.         }
  217.     }
  218.       insymbol ();
  219.     }
  220. }
  221.  
  222. void closelibrary (void)
  223. {
  224.   char libname[MAXIDSIZE], ut_libname[MAXIDSIZE];
  225.   int cc;
  226.   /* close one or more shared libraries */
  227.  
  228.   insymbol ();
  229.   if (sym != ident && sym != stringconst)
  230.     {
  231.       /* 
  232.          ** Close all open shared libraries not 
  233.          ** normally closed by ACE at the end of
  234.          ** the program run.
  235.        */
  236.       cc = 0;
  237.       while (otherlib[cc].name[0] != '\0' &&
  238.          strcmp (otherlib[cc].name, "SENTINEL") != 0)
  239.     {
  240.       gen ("move.l", otherlib[cc].base, "a1");    /* library base in a1 */
  241.       gen ("jsr", "_close_library", "  ");
  242.       gen ("move.l", "#0", otherlib[cc].base);
  243.       enter_XREF ("_close_library");
  244.       cc++;
  245.     }
  246.     }
  247.   else
  248.     {
  249.       /* close a single shared library */
  250.       get_libname (libname, ut_libname);    /* without extension! */
  251.  
  252.       if (check_for_ace_lib (libname) == NEGATIVE)
  253.     {
  254.       make_library_base (libname);
  255.       gen ("move.l", librarybase, "a1");    /* library base in a1 */
  256.       gen ("jsr", "_close_library", "  ");
  257.       gen ("move.l", "#0", librarybase);
  258.       enter_XREF ("_close_library");
  259.     }
  260.       insymbol ();
  261.     }
  262. }
  263.  
  264. void remove_qualifier (char *funcname)
  265. {
  266. /* remove any trailing data type qualifier (%&#!$) @=& [=! */
  267.   int cc = 0;
  268.  
  269.   /* find end of string */
  270.   while (funcname[cc] != '\0')
  271.     cc++;
  272.   /* is the last character a qualifier? */
  273.   if ((funcname[cc - 1] == '%') || (funcname[cc - 1] == '@') || (funcname[cc - 1] == '#')
  274.       || (funcname[cc - 1] == '[') || (funcname[cc - 1] == '$'))
  275.     funcname[cc - 1] = '\0';
  276. }
  277.  
  278.  
  279. BOOL found_func (char *libname, char *ut_funcname, SYM * declared_func)
  280. {
  281.   /* 
  282.      ** Search for function in bmap file and record register usage
  283.      ** and library base offset in symbol table entry for function.
  284.    */
  285.  
  286.   make_bmap_name (libname);
  287.  
  288.   if (search_func (bmapname, ut_funcname, declared_func))
  289.     {
  290.       /* store library name */
  291.       declared_func->libname = (char *) sym_alloc (MAXIDSIZE + 8, MEMF_ANY);
  292.       if (declared_func->libname == NULL)
  293.     {
  294.       puts ("Can't allocate memory for library name in symbol table!");
  295.       early_exit = TRUE;
  296.       kill_all_lists ();
  297.       cleanup ();
  298.     }
  299.       else
  300.     {
  301.       /* found the function */
  302.       strcpy (declared_func->libname, libname);
  303.       return (TRUE);
  304.     }
  305.     }
  306.   else
  307.     /* didn't find the function */
  308.     return (FALSE);
  309. }
  310.  
  311. void declare (void)
  312. {
  313. /* - declare a library function -- NOT optional. 
  314.    - declare an external function -- NOT optional.
  315.    - declare a forward reference to a SUB. 
  316.    - declare an instance of a structure. 
  317.  */
  318.  
  319.   char funcname[MAXIDSIZE], ut_funcname[MAXIDSIZE];
  320.   char libname[MAXIDSIZE], ut_libname[MAXIDSIZE];
  321.   char extfuncname[MAXIDSIZE + 1];
  322.   int oldlevel, cc;
  323.   int functype = undefined;
  324.   SYM *declared_func;
  325.   BOOL found;
  326.  
  327.   /* all functions and structures must be declared at level ZERO */
  328.  
  329.   oldlevel = lev;
  330.   lev = ZERO;
  331.  
  332.   insymbol ();
  333.  
  334.   if (sym == subsym)
  335.     {
  336.       lev = oldlevel;
  337.       forward_ref ();
  338.       return;
  339.     }
  340.  
  341.   if (sym == structsym)
  342.     {
  343.       lev = oldlevel;
  344.       declare_structure ();
  345.       return;
  346.     }
  347.  
  348.   if (sym != functionsym)
  349.     _error (47);
  350.   else
  351.     {
  352.       insymbol ();
  353.  
  354.       /* type identifiers */
  355.       if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  356.       sym == singlesym || sym == stringsym)
  357.     {
  358.       switch (sym)
  359.         {
  360.         case shortintsym:
  361.           functype = shorttype;
  362.           break;
  363.         case longintsym:
  364.           functype = longtype;
  365.           break;
  366.         case addresssym:
  367.           functype = longtype;
  368.           break;
  369.         case singlesym:
  370.           functype = singletype;
  371.           break;
  372.         case stringsym:
  373.           functype = stringtype;
  374.           break;
  375.         }
  376.       insymbol ();
  377.     }
  378.  
  379.       if (sym != ident)
  380.     _error (7);
  381.       else
  382.     {
  383.       /* get the function's name */
  384.       strcpy (funcname, id);
  385.       strcpy (ut_funcname, ut_id);    /* case sensitive version for search! */
  386.       remove_qualifier (funcname);
  387.       remove_qualifier (ut_funcname);
  388.       if (functype == undefined)
  389.         functype = typ;
  390.  
  391.       /* get the LIBRARY symbol and/or parameter list */
  392.       insymbol ();
  393.  
  394.       /* parse parameter list? */
  395.       if (sym == lparen)
  396.         {
  397.           do
  398.         {
  399.           insymbol ();
  400.  
  401.           if (sym == rparen && lastsym == lparen)
  402.             break;    /* FuncName() */
  403.  
  404.           /* type indentifier? */
  405.           if (sym == shortintsym || sym == longintsym || sym == addresssym ||
  406.               sym == singlesym || sym == stringsym)
  407.             insymbol ();
  408.  
  409.           /* parameter */
  410.           if (sym != ident)
  411.             _error (7);
  412.           else
  413.             insymbol ();
  414.         }
  415.           while (sym == comma);
  416.  
  417.           if (sym != rparen)
  418.         _error (9);
  419.           else
  420.         insymbol ();
  421.         }
  422.  
  423.       /* EXTERNAL or LIBRARY function? */
  424.       if (sym == externalsym)
  425.         {
  426.           if (ut_funcname[0] != '_')
  427.         {
  428.           strcpy (extfuncname, "_\0");
  429.           strcat (extfuncname, ut_funcname);
  430.         }
  431.           else
  432.         strcpy (extfuncname, ut_funcname);
  433.  
  434.           enter (extfuncname, functype, extfunc, 0);
  435.           enter_XREF (extfuncname);
  436.  
  437.           insymbol ();
  438.         }
  439.       else if (sym != librarysym)
  440.         _error (48);
  441.       else
  442.         {
  443.           enter (funcname, functype, function, 0);    /* enter into symbol table */
  444.           declared_func = curr_item;
  445.  
  446.           insymbol ();
  447.  
  448.           if (sym != ident && sym != stringconst)
  449.         {
  450.           /* 
  451.              ** Search all bmap files found in acelib and otherlib arrays 
  452.              ** for function since no library was specified.
  453.            */
  454.  
  455.           found = FALSE;
  456.  
  457.           /* acelib array */
  458.           cc = 0;
  459.           while (!found && acelib[cc].name[0] != '\0' &&
  460.              strcmp (acelib[cc].name, "SENTINEL") != 0)
  461.             {
  462.               found = found_func (acelib[cc].name, ut_funcname, declared_func);
  463.               cc++;
  464.             }
  465.  
  466.           if (found)
  467.             {
  468.               lev = oldlevel;
  469.               return;
  470.             }
  471.  
  472.           /* otherlib array */
  473.           cc = 0;
  474.           while (!found && otherlib[cc].name[0] != '\0' &&
  475.              strcmp (otherlib[cc].name, "SENTINEL") != 0)
  476.             {
  477.               found = found_func (otherlib[cc].name, ut_funcname, declared_func);
  478.               cc++;
  479.             }
  480.  
  481.           if (!found)
  482.             _error (49);
  483.         }
  484.           else
  485.         {
  486.           /* 
  487.              ** Search specified library (bmap file) for the declared function.
  488.            */
  489.           get_libname (libname, ut_libname);    /* without extension! */
  490.  
  491.           if (!found_func (libname, ut_funcname, declared_func))
  492.             _error (49);
  493.  
  494.           insymbol ();
  495.         }
  496.         }
  497.     }
  498.     }
  499.   lev = oldlevel;
  500. }
  501.  
  502. void load_func_params (SYM * func_item)
  503. {
  504. /* 
  505.    ** Parse a shared library function's actual parameter-list 
  506.    ** and call the function.
  507.  */
  508.   SHORT i, n;
  509.   char ptemp[14][80];
  510.  
  511.   if (sym != lparen)
  512.     {
  513.       _error (14);
  514.       return;
  515.     }
  516.   else
  517.     {
  518.       /* get parameters */
  519.       i = 0;
  520.       do
  521.     {
  522.       insymbol ();
  523.  
  524.       /*
  525.          ** Make ALL parameters longints! 
  526.        */
  527.       if (expr () == shorttype)
  528.         make_long ();
  529.  
  530.       /* 
  531.          ** Store parameter information temporarily 
  532.          ** since expression evaluation may corrupt 
  533.          ** data in registers later if loaded now.
  534.        */
  535.       make_temp_long ();
  536.       strcpy (ptemp[i], templongname);    /* later -> move.l srctemp,addrbuf */
  537.  
  538.       /* store it */
  539.       gen ("move.l", "(sp)+", templongname);
  540.  
  541.       i++;
  542.     }
  543.       while ((i < func_item->no_of_params) && (sym == comma));
  544.  
  545.       if ((i < func_item->no_of_params) || (sym == comma))
  546.     _error (39);        /* parameter count mismatch - too few or too many. */
  547.       else
  548.     {
  549.       /* load parameters into regs */
  550.       for (n = 0; n < func_item->no_of_params; n++)
  551.         {
  552.           /* does reg (a4 or a5 ONLY) need to be preserved? */
  553.           if (func_item->reg[n] == 13)    /* a4 */
  554.         {
  555.           restore_a4 = TRUE;
  556.           gen ("move.l", "a4", "_a4_temp");
  557.           enter_BSS ("_a4_temp:", "ds.l 1");
  558.         }
  559.           else if (func_item->reg[n] == 14)        /* a5 */
  560.         {
  561.           restore_a5 = TRUE;
  562.           gen ("move.l", "a5", "_a5_temp");
  563.           enter_BSS ("_a5_temp:", "ds.l 1");
  564.         }
  565.  
  566.           /*
  567.              ** Store value in register.
  568.            */
  569.           gen ("move.l", ptemp[n], reg[func_item->reg[n]]);
  570.         }
  571.     }
  572.  
  573.       if (sym != rparen)
  574.     _error (9);
  575.     }
  576. }
  577.  
  578. /* ----------------- */
  579. /* Machine Code CALL */
  580. /* ----------------- */
  581.  
  582. void load_mc_params (SYM * sub_ptr)
  583. {
  584.   SHORT i, n;
  585.   int ptype;
  586.   char p_temp[MAXPARAMS][80];
  587.   int p_type[MAXPARAMS];
  588.  
  589.   /* 
  590.      ** Store parameters in stack space of MC subroutine 
  591.      ** which is about to be CALLed ala C parameter passing 
  592.      ** convention.
  593.    */
  594.  
  595.   i = 0;
  596.   do
  597.     {
  598.       insymbol ();
  599.       ptype = expr ();
  600.  
  601.       /* store parameters temporarily */
  602.       if (ptype == shorttype)
  603.     {
  604.       /* save parameter type */
  605.       p_type[i] = shorttype;    /* not DATA type but STORE type (2 or 4 bytes) */
  606.  
  607.       /* create a temporary store */
  608.       make_temp_short ();
  609.       strcpy (p_temp[i], tempshortname);    /* later -> move.w srctemp,-(sp) */
  610.  
  611.       /* store it */
  612.       gen ("move.w", "(sp)+", tempshortname);
  613.     }
  614.       else
  615.     /* long,single,string or array */
  616.     {
  617.       /* save parameter type */
  618.       p_type[i] = longtype;    /* storage requirement is 4 bytes */
  619.  
  620.       /* create a temporary store */
  621.       make_temp_long ();
  622.       strcpy (p_temp[i], templongname);
  623.  
  624.       /* store it */
  625.       gen ("move.l", "(sp)+", templongname);
  626.     }
  627.  
  628.       i++;
  629.     }
  630.   while ((i < MAXPARAMS) && (sym == comma));
  631.  
  632.   /* push parameters onto stack ala C (see AmigaBASIC manual 6-11) */
  633.   for (n = i - 1; n >= 0; n--)
  634.     {
  635.       if (p_type[n] == shorttype)
  636.     {
  637.       gen ("move.w", p_temp[n], "-(sp)");    /* short */
  638.       sub_ptr->p_type[n] = shorttype;
  639.     }
  640.       else
  641.     {
  642.       gen ("move.l", p_temp[n], "-(sp)");    /* long,string,single,array */
  643.       sub_ptr->p_type[n] = longtype;
  644.     }
  645.     }
  646.  
  647.   sub_ptr->no_of_params = i;    /* record number of parameters pushed! */
  648.  
  649.   if (sym != rparen)
  650.     _error (9);
  651. }
  652.